﻿using System.Collections;
using System.Collections.Generic;
using System.Data;
using BBCode.Tags;

namespace BBCode.Collections
{
    /// <summary>
    /// A collection of Tags
    /// </summary>
    public class TagCollection : ICollection<ITag>
    {
        private IDictionary<string, ITag> _collection = new Dictionary<string, ITag>();

        /// <summary>
        /// Gets the enumerator.
        /// </summary>
        /// <returns></returns>
        public IEnumerator<ITag> GetEnumerator()
        {
            return _collection.Values.GetEnumerator();
        }

        /// <summary>
        /// Returns an enumerator that iterates through a collection.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
        /// </returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="TagCollection"/> class.
        /// </summary>
        public TagCollection()
        {
            
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="TagCollection"/> class with the supplied items.
        /// </summary>
        /// <param name="items">The items.</param>
        public TagCollection(IEnumerable<ITag> items)
        {
            foreach(ITag item in items)
            {
                Add(item);
            }
        }

        /// <summary>
        /// Adds the specified item.
        /// </summary>
        /// <param name="item">The item.</param>
        public void Add(ITag item)
        {
            //Check if key already present!
            if (_collection.ContainsKey(item.Name))
            {
                throw new DuplicateNameException("An ITag with the same name already exists in the collection.");
            }
            _collection.Add(item.Name, item);
        }

        /// <summary>
        /// Removes the range.
        /// </summary>
        /// <param name="items">The items.</param>
        public void RemoveRange(IEnumerable<ITag> items)
        {
            foreach (var item in items)
            {
                Remove(item);
            }
        }

        /// <summary>
        /// Clears this instance.
        /// </summary>
        public void Clear()
        {
            _collection.Clear();
        }

        /// <summary>
        /// Determines whether the collection [contains] [the specified item].
        /// </summary>
        /// <param name="item">The item.</param>
        /// <returns>
        ///   <c>true</c> if the collection [contains] [the specified item]; otherwise, <c>false</c>.
        /// </returns>
        public bool Contains(ITag item)
        {
            return _collection.ContainsKey(item.Name);
        }

        /// <summary>
        /// Copies to.
        /// </summary>
        /// <param name="array">The array.</param>
        /// <param name="arrayIndex">Index of the array.</param>
        public void CopyTo(ITag[] array, int arrayIndex)
        {
            _collection.Values.CopyTo(array, arrayIndex);
        }

        /// <summary>
        /// Removes the specified item.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <returns></returns>
        public bool Remove(ITag item)
        {
            return _collection.Remove(item.Name);
        }

        /// <summary>
        /// Gets the count.
        /// </summary>
        public int Count
        {
            get { return _collection.Count; }
        }

        /// <summary>
        /// Gets a value indicating whether this instance is read only.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is read only; otherwise, <c>false</c>.
        /// </value>
        public bool IsReadOnly
        {
            get { return _collection.IsReadOnly; }
        }
    }
}
